import {
  Controller,
  Get,
  Post,
  Put,
  Delete,
  Body,
  Param,
  Query,
  Req,
  UseGuards,
  UseInterceptors,
  HttpStatus,
  ParseUUIDPipe,
  ParseIntPipe,
  DefaultValuePipe,
} from '@nestjs/common';
import {
  ApiTags,
  ApiOperation,
  ApiResponse,
  ApiParam,
  ApiQuery,
  // ApiBearerAuth,
  ApiBody,
} from '@nestjs/swagger';
import { Request } from 'express';
import { ThrottlerGuard } from '@nestjs/throttler';
import { CacheInterceptor } from '@nestjs/cache-manager';
import { RoomsService } from './rooms.service';
import {
  CreateRoomDto,
  JoinRoomDto,
  UpdateRoomDto,
  UpdateParticipantDto,
} from './dto/create-room.dto';
import {
  RoomResponseDto,
  ParticipantResponseDto,
  CreateRoomResponseDto,
  JoinRoomResponseDto,
  RoomListResponseDto,
  RoomStatsResponseDto,
} from './dto/room-response.dto';

@ApiTags('房间管理')
@Controller('rooms')
@UseGuards(ThrottlerGuard)
export class RoomsController {
  constructor(private readonly roomsService: RoomsService) {}

  @Post()
  @ApiOperation({ summary: '创建房间' })
  @ApiBody({ type: CreateRoomDto })
  @ApiResponse({
    status: HttpStatus.CREATED,
    description: '房间创建成功',
    type: CreateRoomResponseDto,
  })
  @ApiResponse({
    status: HttpStatus.BAD_REQUEST,
    description: '请求参数错误',
  })
  @ApiResponse({
    status: HttpStatus.TOO_MANY_REQUESTS,
    description: '请求过于频繁',
  })
  async createRoom(
    @Body() createRoomDto: CreateRoomDto,
    @Req() req: Request,
  ): Promise<CreateRoomResponseDto> {
    const creatorId = this.extractUserId(req);
    const creatorIp = this.extractClientIp(req);

    return await this.roomsService.createRoom(
      createRoomDto,
      creatorId,
      creatorIp,
    );
  }

  @Post(':roomId/join')
  @ApiOperation({ summary: '加入房间' })
  @ApiParam({ name: 'roomId', description: '房间ID', type: 'string' })
  @ApiBody({ type: JoinRoomDto })
  @ApiResponse({
    status: HttpStatus.OK,
    description: '成功加入房间',
    type: JoinRoomResponseDto,
  })
  @ApiResponse({
    status: HttpStatus.NOT_FOUND,
    description: '房间不存在',
  })
  @ApiResponse({
    status: HttpStatus.BAD_REQUEST,
    description: '房间已满或已过期',
  })
  @ApiResponse({
    status: HttpStatus.FORBIDDEN,
    description: '房间密码错误',
  })
  async joinRoom(
    @Param('roomId', ParseUUIDPipe) roomId: string,
    @Body() joinRoomDto: JoinRoomDto,
    @Req() req: Request,
  ): Promise<JoinRoomResponseDto> {
    const userId = this.extractUserId(req);
    const socketId = this.generateSocketId();
    const ipAddress = this.extractClientIp(req);
    const userAgent = req.headers['user-agent'];

    joinRoomDto.roomId = roomId;

    return await this.roomsService.joinRoom(
      joinRoomDto,
      userId,
      socketId,
      ipAddress,
      userAgent,
    );
  }

  @Post(':roomId/leave')
  @ApiOperation({ summary: '离开房间' })
  @ApiParam({ name: 'roomId', description: '房间ID', type: 'string' })
  @ApiResponse({
    status: HttpStatus.OK,
    description: '成功离开房间',
  })
  @ApiResponse({
    status: HttpStatus.NOT_FOUND,
    description: '房间或参与者不存在',
  })
  async leaveRoom(
    @Param('roomId', ParseUUIDPipe) roomId: string,
    @Req() req: Request,
  ): Promise<{ message: string }> {
    const userId = this.extractUserId(req);

    await this.roomsService.leaveRoom(roomId, userId);

    return { message: '成功离开房间' };
  }

  @Get(':roomId')
  @ApiOperation({ summary: '获取房间信息' })
  @ApiParam({ name: 'roomId', description: '房间ID', type: 'string' })
  @ApiQuery({
    name: 'includeParticipants',
    description: '是否包含参与者信息',
    type: 'boolean',
    required: false,
  })
  @ApiResponse({
    status: HttpStatus.OK,
    description: '获取房间信息成功',
    type: RoomResponseDto,
  })
  @ApiResponse({
    status: HttpStatus.NOT_FOUND,
    description: '房间不存在',
  })
  @UseInterceptors(CacheInterceptor)
  async getRoomById(
    @Param('roomId', ParseUUIDPipe) roomId: string,
    @Query('includeParticipants') includeParticipants?: boolean,
  ): Promise<RoomResponseDto> {
    return await this.roomsService.getRoomById(roomId, includeParticipants);
  }

  @Put(':roomId')
  @ApiOperation({ summary: '更新房间信息' })
  @ApiParam({ name: 'roomId', description: '房间ID', type: 'string' })
  @ApiBody({ type: UpdateRoomDto })
  @ApiResponse({
    status: HttpStatus.OK,
    description: '房间信息更新成功',
    type: RoomResponseDto,
  })
  @ApiResponse({
    status: HttpStatus.NOT_FOUND,
    description: '房间不存在',
  })
  @ApiResponse({
    status: HttpStatus.FORBIDDEN,
    description: '无权限更新房间信息',
  })
  async updateRoom(
    @Param('roomId', ParseUUIDPipe) roomId: string,
    @Body() updateRoomDto: UpdateRoomDto,
    @Req() req: Request,
  ): Promise<RoomResponseDto> {
    const userId = this.extractUserId(req);

    return await this.roomsService.updateRoom(roomId, updateRoomDto, userId);
  }

  @Put(':roomId/participants/:userId')
  @ApiOperation({ summary: '更新参与者信息' })
  @ApiParam({ name: 'roomId', description: '房间ID', type: 'string' })
  @ApiParam({ name: 'userId', description: '用户ID', type: 'string' })
  @ApiBody({ type: UpdateParticipantDto })
  @ApiResponse({
    status: HttpStatus.OK,
    description: '参与者信息更新成功',
    type: ParticipantResponseDto,
  })
  @ApiResponse({
    status: HttpStatus.NOT_FOUND,
    description: '参与者不存在',
  })
  async updateParticipant(
    @Param('roomId', ParseUUIDPipe) roomId: string,
    @Param('userId') userId: string,
    @Body() updateParticipantDto: UpdateParticipantDto,
  ): Promise<ParticipantResponseDto> {
    return await this.roomsService.updateParticipant(
      roomId,
      userId,
      updateParticipantDto,
    );
  }

  @Get()
  @ApiOperation({ summary: '获取房间列表' })
  @ApiQuery({
    name: 'page',
    description: '页码',
    type: 'number',
    required: false,
    example: 1,
  })
  @ApiQuery({
    name: 'limit',
    description: '每页数量',
    type: 'number',
    required: false,
    example: 10,
  })
  @ApiQuery({
    name: 'status',
    description: '房间状态',
    enum: ['waiting', 'active', 'ended'],
    required: false,
  })
  @ApiQuery({
    name: 'creatorId',
    description: '创建者ID',
    type: 'string',
    required: false,
  })
  @ApiResponse({
    status: HttpStatus.OK,
    description: '获取房间列表成功',
    type: RoomListResponseDto,
  })
  @UseInterceptors(CacheInterceptor)
  async getRooms(
    @Query('page', new DefaultValuePipe(1), ParseIntPipe) page: number,
    @Query('limit', new DefaultValuePipe(10), ParseIntPipe) limit: number,
    @Query('status') status?: string,
    @Query('creatorId') creatorId?: string,
  ): Promise<RoomListResponseDto> {
    return await this.roomsService.getRooms(page, limit, status, creatorId);
  }

  @Get('stats/overview')
  @ApiOperation({ summary: '获取房间统计信息' })
  @ApiResponse({
    status: HttpStatus.OK,
    description: '获取统计信息成功',
    type: RoomStatsResponseDto,
  })
  @UseInterceptors(CacheInterceptor)
  async getRoomStats(): Promise<RoomStatsResponseDto> {
    return await this.roomsService.getRoomStats();
  }

  @Delete(':roomId')
  @ApiOperation({ summary: '删除房间' })
  @ApiParam({ name: 'roomId', description: '房间ID', type: 'string' })
  @ApiResponse({
    status: HttpStatus.OK,
    description: '房间删除成功',
  })
  @ApiResponse({
    status: HttpStatus.NOT_FOUND,
    description: '房间不存在',
  })
  @ApiResponse({
    status: HttpStatus.FORBIDDEN,
    description: '无权限删除房间',
  })
  async deleteRoom(
    @Param('roomId', ParseUUIDPipe) roomId: string,
    @Req() req: Request,
  ): Promise<{ message: string }> {
    const userId = this.extractUserId(req);

    await this.roomsService.deleteRoom(roomId, userId);

    return { message: '房间删除成功' };
  }

  @Post('cleanup/expired')
  @ApiOperation({ summary: '清理过期房间' })
  @ApiResponse({
    status: HttpStatus.OK,
    description: '清理完成',
    schema: {
      type: 'object',
      properties: {
        message: { type: 'string' },
        cleanedCount: { type: 'number' },
      },
    },
  })
  async cleanupExpiredRooms(): Promise<{
    message: string;
    cleanedCount: number;
  }> {
    const cleanedCount = await this.roomsService.cleanupExpiredRooms();

    return {
      message: '过期房间清理完成',
      cleanedCount,
    };
  }

  // 私有辅助方法
  private extractUserId(req: Request): string {
    // 从请求头或JWT token中提取用户ID
    // 这里简化处理，实际应该从认证中间件获取
    const userId = req.headers['x-user-id'] as string;
    return (
      userId || `user_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
    );
  }

  private extractClientIp(req: Request): string {
    return (
      (req.headers['x-forwarded-for'] as string)?.split(',')[0] ||
      req.connection.remoteAddress ||
      req.socket.remoteAddress ||
      '127.0.0.1'
    );
  }

  private generateSocketId(): string {
    return `socket_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
  }
}
